;;; indexwsgi-mode.el --- mode for sinaapp's index.wsgi file

;; Copyright (C) 2011 zxy
;; Author: zxy <gcoordinate@gmail.com>
;; Maintainer: zxy <gcoordinate@gmail.com>
;; Created: Dec 2011
;; Version: 1.3.1

;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;; Installation instructions
;; --------------------------------
;; (setq sae-python-root-path (concat program-path"saepythondevguide/dev_server/"))
;; (setq django-lib-path (concat program-path"django/"))
;; (add-to-list 'load-path (concat plugin-path "appengine-emacs-toolkit"))
;; (require 'indexwsgi-mode)
;; (add-hook 'indexwsgi-mode-hook
;;           (lambda ()
;;             (progn (local-set-key "\C-cc" 'sae-python-start-appserver)
;;                    (local-set-key "\C-cb" 'appengine-browse-appserver)
;;                    (local-set-key "\C-cu" 'sae-python-update-appserver))))

(load-file (replace-regexp-in-string "indexwsgi-mode.el" "appengine-common.el" load-file-name))
(load-file (replace-regexp-in-string "indexwsgi-mode.el" "appengine-django.el" load-file-name))
(message (concat "Loading " load-file-name))

;; public var

(defvar sae-python-root-path nil
  "*path of sae")

(defvar sae-priority-python-version "26"
  "*Priority python version")

(defvar sae-template-directory-python26
  (concat (file-name-directory (or load-file-name buffer-file-name))"new_project_template_sae_python26")
  "*Project template for python26")

(defvar sae-template-directory-python26-django
  (concat (file-name-directory (or load-file-name buffer-file-name))
          "new_project_template_sae_python26_django1.2.7")
  "*Project template for python26 with django")

;; private var

(defvar sae-priority-project-version nil
  "*Priority project version")

(defun* sae-python-start-appserver (&optional (port nil))
  "Open shell to start sae appserver"
  (interactive)
  (save-buffer buffer-file-name)
  (unless (and (not (equal nil sae-python-root-path))
               (file-exists-p sae-python-root-path))
      (error "[appengine] Cannot find sae-python-root-path."))
  (if (eq nil port)
      (progn
        (appengine-check-server-hash buffer-file-name)
        (setq port appengine-server-port)))
  (setq bufname (concat "*sae-appserver-"port"*"))
  (if (not (eq nil (get-buffer bufname)))
      (kill-buffer bufname))
  (setq proname (replace-regexp-in-string "index.wsgi" "" buffer-file-name))
  (shell bufname)
  (comint-send-string (current-buffer) (concat "echo '[appengine] AppServer Starting "proname"...' \n"))
  (if (eq system-type 'windows-nt)
      (comint-send-string (current-buffer) (concat "python \""sae-python-root-path"/dev_server.py\" --port="port" \n"))
    (comint-send-string (current-buffer) (concat "python \""sae-python-root-path"/dev_server.py\" --port="port" \n")))
  (end-of-buffer)
  (other-window -1))

(defun sae-python-checkout-appserver ()
  "Checkout appserver from svn"
  (interactive)
  (if (equal nil buffer-file-name)
      (setq tmpprojectpath "~/")
    (setq tmpprojectpath (file-name-directory buffer-file-name)))
  (let ((projectpath (read-string "[appengine] Checkout path: "
                                  tmpprojectpath nil tmpprojectpath nil))
        (projectname (read-string "[appengine] Project name (default blackfire): "
                                  nil nil "blackfire" nil)))
    (shell "*appengine-temp*")
    (comint-send-string (current-buffer) (concat "cd '"projectpath"' \n"))
    (comint-send-string (current-buffer) (concat "echo '[appengine] AppServer checkout "projectname"...' \n"))
    (comint-send-string (current-buffer) (concat "svn co https://svn.sinaapp.com/"projectname"\n"))
    ))

(defun sae-python-update-appserver ()
  "Update appserver"
  (interactive)
  (let ((commitstr (read-string "[appengine] Commit message: " nil nil "" nil)))
    (save-some-buffers)
    (setq proname (replace-regexp-in-string "index.wsgi" "" buffer-file-name))
    (shell "*appengine-temp*")
    (comint-send-string (current-buffer) (concat "echo '[appengine] AppServer Updateing "proname"...' \n"))
    (comint-send-string (current-buffer) (concat "cd '"proname"' \n"))
    (comint-send-string (current-buffer) (concat "cd .. \n"))
    (comint-send-string (current-buffer) (concat "svn ci -m '"commitstr"'\n"))
    (end-of-buffer)
    (other-window -1)))

;; For projectn

(defun sae-get-priority-project-version (projectpath)
  "Get priority project version by find numbered folder. now support v99"
  (setq sae-priority-project-version "0")
  (while (progn
           (setq sae-priority-project-version
                 (number-to-string (+ (string-to-int sae-priority-project-version) 1)))
           (file-exists-p (concat projectpath"/"sae-priority-project-version)))))

(defun sae-python-create-project-basic (projectpath projectname pythonver projectver)
  "Create new project"
  (when (equal pythonver "26")
    (setq sae-template-directory sae-template-directory-python26))
  (unless (file-exists-p sae-template-directory)
    (error "[appengine] Cannot find sae template directory!"))
  (when (file-exists-p (concat projectpath"/"projectver))
    (find-file (concat projectpath"/"projectver))
    (error (format "[appengine] Version%s exist!" projectver)))
  (unless (file-exists-p projectpath)
    (make-directory projectpath t))
  (copy-directory (concat sae-template-directory"/1") (concat projectpath"/"projectver))
  (find-file (concat projectpath"/"projectver"/index.wsgi")))

(defun sae-python-create-project-django (projectpath projectname pythonver projectver)
  "Create new project"
  (when (equal pythonver "26")
    (setq sae-template-directory sae-template-directory-python26-django))
  (unless (file-exists-p sae-template-directory)
    (error "[appengine] Cannot find sae template directory!"))
  (when (file-exists-p (concat projectpath"/"projectver))
    (error (format "[appengine] Version%s exist!" projectver)))
  (unless (file-exists-p projectpath)
    (make-directory projectpath t))
  (let ((djprojectname (read-string "[appengine] Django Project name (default mysite): "
                                         nil nil "mysite" nil)))
    (copy-directory (concat sae-template-directory"/1")
                    (concat projectpath"/"projectver))
    (find-file (concat projectpath"/"projectver"/index.wsgi"))
    (beginning-of-buffer)
    (replace-string "mysite" djprojectname)
    (beginning-of-buffer)
    (save-buffer buffer-file-name)
    (django-new-project (concat projectpath"/"projectver) djprojectname)
    ))

(defun sae-python-new-project ()
  "Create new project"
  (interactive)
  (unless (and (not (equal nil sae-python-root-path))
               (file-exists-p sae-python-root-path))
    (error "[appengine] Cannot find sae-python-root-path!"))
  (if (equal nil buffer-file-name)
      (setq tmpprojectpath "~/")
    (setq tmpprojectpath (file-name-directory buffer-file-name)))
  ;; read information from mini buffer
  (let ((projectpath (read-string "[appengine] Project path: "
                                  tmpprojectpath nil tmpprojectpath nil))
        (projectname (read-string "[appengine] Project name (default sae-python-project): "
                                  nil nil "sae-python-project" nil)))
    (setq projectpath (concat projectpath"/"projectname))
    (if (file-exists-p projectpath)
        (sae-get-priority-project-version projectpath)
      (setq sae-priority-project-version "1"))
    (let ((projectver (read-string (format "[appengine] Project version (default %s): "
                                           sae-priority-project-version) nil nil
                                           sae-priority-project-version nil))
          (projecttype (read-string (format "[appengine] Project type (%s %s): "
                                            "0. hello-wold;"
                                            "1. django;")
                                    nil nil "0" nil)))
      (setq projectver (ceiling (string-to-int projectver)))
      (if (< projectver (string-to-int sae-priority-project-version))
          (error (format "[appengine] Version%s exist!" projectver)))
      (when (or (= projectver (string-to-int sae-priority-project-version))
                (and (> projectver (string-to-int sae-priority-project-version))
                     (y-or-n-p (format "[appengine] Version%s not exist! Build version%s?"
                                       sae-priority-project-version projectver))))
        (setq projectver (number-to-string projectver))
        ;; basic
        (when (equal "0" projecttype)
          (sae-python-create-project-basic projectpath projectname sae-priority-python-version projectver))
        ;; django
        (when (equal "1" projecttype)
          (sae-python-create-project-django projectpath projectname sae-priority-python-version projectver))

        ))))

;; define the major mode.

(define-derived-mode indexwsgi-mode python-mode "indexwsgi"
  "indexwsgi-mode is a major mode for sina app engine index.wsgi file."
  )

(add-to-list 'auto-mode-alist '("\\index.wsgi\\'" . indexwsgi-mode))

(provide 'indexwsgi-mode)

;;; indexwsgi-mode.el ends here